﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;

namespace Logger
{
    public class Log
    {
        #region "Private attributes"

        private static Log _instance;

        private System.IO.StreamWriter _writer;

        private int _seq;

        private Boolean _DbConnected;

        private String _DbName = "DnD.s3db";

        private const string _sConnect = "Data Source=DnD.s3db";

        private SQLiteConnection _DataConnection;

        private SQLiteCommand _DataCommand;

        private String iRequest = "Insert into Trace(Function, Trace, TraceType, Params, tDate) Values(";

        

        // useless now
        //private int _fileMaxSize;

        #endregion

        #region "Properties"

        public String CurrentFile { get; set; }
        public static Boolean Active { get; set; }

        private SQLiteConnection Connection
        {
            get
            {
                if (_DataConnection == null)
                {
                    _DataConnection = new SQLiteConnection(_sConnect);
                }
                if (_DataConnection.State == System.Data.ConnectionState.Closed)
                {
                    _DataConnection.Open();
                }
                return _DataConnection;
            }
        }

        private SQLiteCommand Command
        {
            get
            {
                if (_DataCommand == null || _DataCommand.Connection == null)
                {
                    _DataCommand = new SQLiteCommand(Connection);
                }

                return _DataCommand;
            }
        }

        #endregion

        #region "Events"
        #endregion

        #region "Public functions"



        public static Log GetInstance()
        {
            if (_instance == null)
            {
                _instance = new Log();
            }
            return _instance;
        }

        public static void Close()
        {
            if (_instance != null)
            {
                if (_instance._DbConnected == false)
                {
                    _instance._writer.Close();
                    _instance._writer.Dispose();
                }
            }
        }

        public static void TraceError(String Function,Exception ex)
        {
            if(Active)
                GetInstance().Trace("Error", Function, ex + "obj=" + ex.Source);
        }

        public static void TraceAction(String Function,String Message)
        {
            if (Active)
                GetInstance().Trace("Action", Function, Message);
        }

        public void Trace(String Type, String Function, String Message)
        {
            if (_DbConnected)
            {  
                var req = iRequest;
                if(Type == "Error")
                {
                    Type = "1";
                }
                else
                {
                    Type = "2";
                }

                req += "'" + Function + "'," + "'" + Message + "'," + Type + ",null,'" + DateTime.Now + "'";
                req += ");";

                Insert(req);
            }
            else
            {
                var trace = "[" + DateTime.Now + "] - " + Type + ":" + Function + "-_-" + Message;
                _writer.WriteLine(trace);
            }           
        }

        public System.Data.DataTable ViewDbTrace()
        {
            System.Data.DataTable table = new System.Data.DataTable();
            if (this._DbConnected)
            {
                try
                {

                    Command.CommandText = "Select * from Trace;";

                    var reader = Command.ExecuteReader();
                    table.Load(reader);
                    reader.Close();
                }
                catch (Exception)
                {
                
                }
                finally
                {
                    Connection.Close();
                    Command.Clone();
                }
            }
            return table;
        }

        #endregion

        #region "Private functions"

        private Log()
        {

            //Insertion of log in database.
            //If Database not found,
            // Creation of log file in AppFolder\Logs
            // If exist, verify size. if logs is too big, create another log file
            // Log file name will be : dnd - <SEQ>.log
            // Log text will be like that : [Date-Hour] - <Type> : <Function>, <Message>
            // Type : Error, User, Auto
            // Function : Name of the function
            // Message: error message, function parameters, webResponse
            ConnectDb();
            if (!_DbConnected)
            {
                OpenLogFile();
            }
        }

        #region "Db functions"

        private void ConnectDb()
        {
            try
            {
                if (!System.IO.File.Exists(_DbName))
                {
                    Command.CommandText = SqlReader("Sql/Create.sql");
                    Command.ExecuteNonQuery();
                }
                _DbConnected = true;
            }
            catch (Exception)
            {
                _DbConnected = false;
            }
        }

        private String SqlReader(String fileName)
        {
            var sql = "";
            System.IO.StreamReader reader = null;
            try
            {
                reader = new System.IO.StreamReader(fileName);
                sql = reader.ReadToEnd();
            }
            catch (Exception)
            {
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader.Dispose();
                }
            }
            return sql;
        }


        public int Insert(String Request)
        {
            var Ok = 0;
            try
            {
                Command.CommandText = Request;
                Ok = Command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
            }
            finally
            {
                Connection.Close();
                Command.Dispose();
            }
            return Ok;
        }

        #endregion

       

        private void OpenLogFile()
        {
            try
            {
                _seq = 1;


                if (!System.IO.Directory.Exists("log"))
                {
                    System.IO.Directory.CreateDirectory("log");
                }

                CurrentFile = "log/DnD - " + _seq + ".log";
                _writer = new System.IO.StreamWriter(CurrentFile, true);
                _writer.AutoFlush = true;
            }
            catch (Exception)
            {
                
                throw;
            }
           
        }

        #endregion

    }

}
